﻿/// Copyright 2011 - Agus Kurniawan
/// Blog: http://blog.aguskurniawan.net 
/// ====================================================================

using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Diagnostics;
using Microsoft.Win32;

namespace Galunggung
{
    internal class MacAddress
    {
        private const string regNic = "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";

        public static List<NicInfo> GetNetworkInterfaces()
        {
            List<NicInfo> list = new List<NicInfo>();

            NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface adapter in nics)
            {
                if (adapter.NetworkInterfaceType == NetworkInterfaceType.Ethernet ||
                    adapter.NetworkInterfaceType == NetworkInterfaceType.Ethernet3Megabit ||
                    adapter.NetworkInterfaceType == NetworkInterfaceType.FastEthernetFx ||
                    adapter.NetworkInterfaceType == NetworkInterfaceType.FastEthernetT ||
                    adapter.NetworkInterfaceType == NetworkInterfaceType.Wireless80211)
                {
                    NicInfo o = new NicInfo();
                    o.Id = adapter.Id;
                    o.Status = adapter.OperationalStatus.ToString();
                    o.Name = adapter.Name;
                    o.Description = adapter.Description;
                    o.MACAdress = BitConverter.ToString(adapter.GetPhysicalAddress().GetAddressBytes());
                    IPInterfaceProperties properties = adapter.GetIPProperties();

                    if (properties.UnicastAddresses.Count > 0)
                    {
                        for (int i = 0; i < properties.UnicastAddresses.Count; i++)
                        {
                            if (properties.UnicastAddresses[i].Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                            {
                                if (properties.UnicastAddresses[i].Address != null)
                                    o.IPAddress = properties.UnicastAddresses[i].Address.ToString();
                                else
                                    o.IPAddress = "0.0.0.0";
                                if (properties.UnicastAddresses[i].IPv4Mask != null)
                                    o.IPMask = properties.UnicastAddresses[i].IPv4Mask.ToString();
                                else
                                    o.IPMask = "0.0.0.0";

                                break;
                            }
                        }
                    }

                    list.Add(o);
                }

            }

            return list;
        }

        public static List<NicInfo> Synch()
        {
            List<NicInfo> list1 = GetNetworkInterfaces();
            List<NicInfo> list2 = MapNicReg(list1);
            List<NicInfo> list3 = new List<NicInfo>();
            SqlMacAddress data = SqlMacAddress.Create();
            for (int i = 0; i < list2.Count; i++)
            {
                NicInfo tmp = data.GetNic(list1[i].Id);
                if (tmp == null)
                    data.InsertNic(list2[i]);
                else
                    data.UpdateNicHardware(list2[i]);

                tmp = data.GetNic(list1[i].Id);
                if (tmp!=null)
                    list3.Add(tmp);
            }

            return list3;
        }

        private static List<NicInfo> MapNicReg(List<NicInfo> listNic)
        {
            List<NicInfo> maps = new List<NicInfo>();
            RegistryKey key = Registry.LocalMachine.OpenSubKey(regNic);
            List<string> list = new List<string>(key.GetSubKeyNames());

            for (int i = 0; i < list.Count; i++)
            {
                if (list[i].ToLower() != "properties")
                {
                    RegistryKey iKey = Registry.LocalMachine.OpenSubKey(regNic + list[i]);
                    string info = Convert.ToString(iKey.GetValue("DriverDesc"));

                    for (int j = 0; j < listNic.Count; j++)
                    {
                        if (listNic[j].Description.ToLower().Trim() == info.ToLower().Trim())
                        {
                            NicInfo tmp = listNic[j];
                            tmp.RegId = list[i];

                            maps.Add(tmp);
                            break;
                        }
                    }                        
                    iKey.Close();
                }
            }

            key.Close();

            return maps;
        }

        public static bool Activate(NicInfo nic)
        {
            try
            {
                PerformNic(nic.Name, false);

                string reg1 = string.Format("{0}\\{1}", regNic, nic.RegId);
                RegistryKey key1 = Registry.LocalMachine.OpenSubKey(reg1, true);                
                key1.SetValue("NetworkAddress", nic.SpoofedMACAdress);
                key1.Close();

                SqlMacAddress data = SqlMacAddress.Create();
                data.UpdateNicSpoofed(nic);

                PerformNic(nic.Name, true);
            }
            catch (Exception err)
            {
                Debug.WriteLine(String.Format("{0}\r\n{1}", err.Message, err.StackTrace));
                return false;
            }
            return true;
        }

        public static bool Restore(NicInfo nic)
        {
            try
            {
                PerformNic(nic.Name, false);
                string reg1 = string.Format("{0}\\{1}", regNic, nic.RegId);
                RegistryKey key1 = Registry.LocalMachine.OpenSubKey(reg1, true);
                key1.DeleteValue("NetworkAddress");
                key1.Close();

                SqlMacAddress data = SqlMacAddress.Create();
                nic.SpoofedMACAdress = "";
                nic.SpoofedMACAdressId = 0;
                data.UpdateNicSpoofed(nic);

                PerformNic(nic.Name, true);
            }
            catch (Exception err)
            {
                Debug.WriteLine(String.Format("{0}\r\n{1}", err.Message, err.StackTrace));
                return false;
            }

            return true;
        }

        public static void PerformNic(string nicName, bool state)
        {
            string cmd = string.Empty;
            if (state)
                cmd = String.Format("interface set interface \"{0}\" enable", nicName);
            else
                cmd = String.Format("interface set interface \"{0}\" disable", nicName);

            ProcessStartInfo psi = new ProcessStartInfo("netsh", cmd);
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            Process p = new Process();
            
            p.StartInfo = psi;
            p.Start();
            p.WaitForExit();            
        }
            
    }
}
